package belf.migrate.plugin.oracle.listener;

import belf.migrate.api.type.LevelType;
import belf.migrate.core.jdbc.DBFunctionMapping;
import belf.migrate.core.jdbc.FunctionModel;
import belf.migrate.plugin.oracle.antlr.PlSqlParserBaseListener;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
public class Oracle2DMFunctionListener extends PlSqlParserBaseListener {

    /** 迁移任务类型，格式为：源库Catalog-目标库Catalog */
    private final String taskType;

    // 保存找到的有差异的函数
    @Getter
    private List<String> differentFunctions = new ArrayList<>();
    private final Map<String, FunctionModel> mappings;

    public Oracle2DMFunctionListener(String taskType) {
        this.taskType = taskType;
        mappings = DBFunctionMapping.getInstance().getMapping(taskType);
    }

    public Oracle2DMFunctionListener(String sourceCatalog, String sinkCatalog) {
        this.taskType = sourceCatalog + "-" + sinkCatalog;
        mappings = DBFunctionMapping.getInstance().getMapping(taskType);
    }

    public boolean hasAncestor(String ancestorClassName, ParseTree node) {
        ParseTree parent = node.getParent();
        while (parent != null) {
            if (parent.getClass().getName().endsWith(ancestorClassName)) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }

    @Override
    public void visitTerminal(TerminalNode node) {

        if (hasAncestor("Compound_expressionContext", node)) {
            String function = node.getText().toUpperCase(); //函数名转为大写进行比较
            boolean different = mappings.containsKey(function) &&
                    mappings.get(function) != null &&
                    (StringUtils.isEmpty(mappings.get(function).getTo()) || LevelType.isIncompatible(mappings.get(function).getLevel()));
            if (different) {
                log.debug("Found Different Function: {}", function);
                differentFunctions.add(function);
            }
        }
    }


}
